home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ian & Stuart's Australian Mac 1993 September
/
September 93.iso
/
Archives
/
Utilities
/
System
/
FKey
/
FKeys
/
tsv4.0.2
/
src
/
TogSndVol4.0.2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-04
|
9KB
|
292 lines
/*
* ToggleSndVol FKEY 4.0.2
* ©1990-2, by Mike Gleason Jr., NCEMRSoft
* This Think C Source code may be distributed freely.
*
* Think C setup:
* Make a project and add MacTraps. Set Project Type to "Code Resource,"
* and set the TYPE to "FKEY" and the ID number to 7 (or whatever…).
* I also suggest setting the "Attrs" to "purgeable" only, & the name to
* ToggleSndVol 4.0.2. Compile it and merge it with "TSV Installer π.rsrc."
*/
#ifndef __SOUND__
# include <Sound.h>
#endif
#define kCancelButtonID 8 /* id number of "Cancel" */
#define kAboutButtonID 9 /* id number of "?" */
#ifndef NULL
# define NULL ((void *) 0) /* duh */
#endif
#define kSmallButtonSize 15 /* how wide and tall a button is */
#define kButtonMargin 3 /* number of pixels between buttons */
#define kWindowWidth 222 /* dimensions of the window in pixels */
#define kWindowHeight 23
#define kWindowExtend 115 /* Make the window this much longer when */
/* the about button is clicked. */
#define kWNETrapNum 0x60 /* Trap number of WaitNextEvent() */
#define kUnImplTrapNum 0x9F /* Trap number "unimplemented trap" */
#define kMinSleep 30L /* for WaitNextEvent */
/* You can debug the FKEY by making */
/* this an application project, and */
/* the FKEY will run as a tiny app. */
#if __option(a4_globals) /* Is this a code resource project? */
# define FKEY
#endif
/* function prototypes... */
void DoIt(void); /* the main event loop */
Boolean ModifierDown(void); /* is the option, shift, or cmd down? */
void SaveToPRAM(short newvol); /* write newvol to the control panel PRAM */
void SetTheVolume(short theVol); /* sets the speaker's volume */
void DoAbout(WindowPtr w);
/* extend the window, show info */
#ifdef FKEY
# include <SetUpA4.h>
#endif
void DoAbout(WindowPtr w)
{
Rect r;
static char text[] =
"ToggleSndVol FKEY 4.0.2\r©1992 by Mike Gleason, NCEMRSoft.\r\rClicking or typing a number sets the sound volume in the Control Panel to that number. Hold"
"ing down the option key will NOT save the result to the PRAM (the change will only last for this boot). This FKEY is FREE, "
"but distribution on media greater than 2MB requires my permission.";
/* All DoAbout() does is stretch the window down when the "?" */
/* button is clicked so I can put up my about info. */
if (w->portRect.bottom > kWindowHeight) return;
/* (The window has already been stretched and is showing the info) */
SetPort(w);
TextFont(geneva);
TextSize(9);
SizeWindow(w, w->portRect.right, w->portRect.bottom + kWindowExtend, TRUE);
r = w->portRect;
r.top = kWindowHeight + 3;
TextBox(text, sizeof (text) - 1, &r, teJustLeft);
} /* DoAbout */
void SaveToPRAM(short newvol)
{
SysPPtr sp;
sp = GetSysPPtr(); /* a pointer to the PRAM */
newvol = (newvol & 0x07) << 8;
/* This block compares 3 bits in our volume to 3 in that of the
sp->volClik field. We can't just say sp->volClik = newvol
because other "useful" data is stored in the other 13 bits
of the field. essentially, this replaces the old 3 bits
with our 3 bits. */
sp->volClik = (sp->volClik & 0xf8ff) | newvol;
(void) WriteParam(); /* now save the changed sp to the PRAM */
} /* SaveToPRAM */
Boolean ModifierDown(void)
{
KeyMap k;
GetKeys(k);
return (
(((char *)k)[7] & 0x05) /* option or shift */
|| (((char *)k)[6] & 0x80) /* command */
);
} /* ModifierDown */
void SetTheVolume(short theVol)
{
/* If the option key is not down, we'll assume the change is */
/* permanent; if it is down, we won't store the change in the PRAM. */
if (!ModifierDown())
SaveToPRAM(theVol);
SetSoundVol(theVol);
SysBeep(3); /* Beep so the user can hear the new volume. */
} /* SetTheVolume */
void DoIt(void)
{
short i, sndVol, ch, done = 0;
long dummy;
Rect itemRect, ScreenBitsBounds, theRect = {0, 0, kWindowHeight, kWindowWidth};
WindowPtr theWind;
ControlHandle buttons[10], whichControl;
Str255 title;
EventRecord theEvent;
Boolean hasWaitNextEvent, haveEvt;
GrafPtr savedPort;
GrafPort tempPort;
GetPort(&savedPort); /* We'll need this later. */
/* find screenBits w/o using quickdraw globals */
OpenPort(&tempPort);
ScreenBitsBounds = tempPort.portRect;
ClosePort(&tempPort);
/* This block of statements creates and centers our window's rectangle. */
OffsetRect(&theRect, (ScreenBitsBounds.right - theRect.right) / 2, (ScreenBitsBounds.bottom - theRect.bottom) / 3);
/* OK, we've got the rectangle, now make the window. */
theWind = NewWindow((Ptr) 0, &theRect, "\p", true, dBoxProc, (WindowPtr) -1, false, 0L);
if (!theWind) return;
/* Get ready to draw in our window */
SetPort(theWind);
SelectWindow(theWind);
/* Create the first button's rectangle. */
theRect.left = theRect.top = 2;
theRect.bottom = theRect.right = theRect.top + kSmallButtonSize;
/* This loop creates 8 little buttons, numbered 0-7. */
for (i=0; i<8; i++) {
NumToString((long) i, title); /* convert 3 to "3", etc. */
buttons[i] = NewControl(
theWind,
&theRect,
title,
true,
0,
0,
0,
pushButProc,
i
);
if (!buttons[i]) return;
/* Shift the rectangle to use for the next button. */
theRect.right += kSmallButtonSize + kButtonMargin;
theRect.left += kSmallButtonSize + kButtonMargin;
}
/* We've already got the rectangle, but it's too narrow. */
/* Add on enough pixels to fit in the word "Cancel." */
theRect.right += /* StringWidth("\pCancel") */ 41;
buttons[kCancelButtonID] = NewControl(theWind, &theRect, "\pCancel", 1,0,0,0,0,kCancelButtonID);
if (!buttons[kCancelButtonID]) return;
/* Grr... Now we need the old dimensions back for a small button. */
theRect.right += kSmallButtonSize + kButtonMargin;
theRect.left = theRect.right - kSmallButtonSize;
buttons[kAboutButtonID] = NewControl(theWind, &theRect, "\p?", 1,0,0,0,0,kAboutButtonID);
if (!buttons[kAboutButtonID]) return;
/* This block gets the current sound volume, so we can put a dot */
/* under the appropriate button in the window to tell the user */
/* what the current speaker volume is. */
GetSoundVol(&sndVol);
theRect.left = ((**buttons[sndVol]).contrlRect.right-(**buttons[sndVol]).contrlRect.left)/2 - 2 + (**buttons[sndVol]).contrlRect.left;
theRect.top = (**buttons[sndVol]).contrlRect.bottom+2;
theRect.right = theRect.left + 4;
theRect.bottom = theRect.top + 4;
PaintOval(&theRect);
hasWaitNextEvent = (Boolean) (NGetTrapAddress(kWNETrapNum, ToolTrap) != NGetTrapAddress(kUnImplTrapNum, ToolTrap));
/* Now everything should be up and running. What follows is a */
/* short and ugly event loop; We only care about mouseDown and */
/* keyDown events. */
while (!done) {
if (hasWaitNextEvent)
haveEvt = WaitNextEvent(everyEvent, &theEvent, kMinSleep, NULL);
else {
SystemTask();
haveEvt = GetNextEvent(everyEvent, &theEvent);
}
if (haveEvt) {
SetPort(theWind);
if (theEvent.what == mouseDown) {
GlobalToLocal(&theEvent.where);
if (FindControl(theEvent.where, theWind, &whichControl)) {
/* see which button it was, and hilite it as needed. */
if (TrackControl(whichControl, theEvent.where, 0L)) {
ch = (short) (**whichControl).contrlRfCon;
goto x; /* it's a "goto," but it saves bytes. */
}
}
} else if (theEvent.what == keyDown || theEvent.what == autoKey) {
ch = (short) (theEvent.message & charCodeMask);
if (ch >= '0' && ch <= '7')
ch -= '0'; /* convert ch to a number */
else if (ch == '/' || ch == '?')
ch = kAboutButtonID; /* about */
else
ch = kCancelButtonID; /* cancel */
whichControl = buttons[ch];
HiliteControl(whichControl, 1); /* psuedoclick the button */
Delay(20L, &dummy);
HiliteControl(whichControl, 0);
x:
done = 1;
if (ch < kCancelButtonID && ch >= 0)
SetTheVolume(ch);
else if (ch == kAboutButtonID) {
DoAbout(theWind);
HiliteControl(whichControl, 255); /* dimmed. */
done = 0;
}
}
}
}
DisposeWindow(theWind);
SetPort(savedPort);
} /* DoIt */
pascal void main(void)
{
#ifdef FKEY
Handle h;
RememberA0(); /* This and the asm stuff guarantees that this code */
SetUpA4(); /* resource is locked while it is executing. */
asm { ;guarantee that it is locked even
_RecoverHandle ; if locked bit was not set with ResEdit.
move.l a0,h ;save away handle to unlock later.
_HLock ;handle is already in a0.
}
InitCursor();
DoIt();
HUnlock(h);
RestoreA4();
#else /* we're testing with an application. */
MaxApplZone();
InitGraf(&thePort);
InitFonts();
FlushEvents(everyEvent, 0);
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
InitCursor();
DoIt();
#endif
} /* main */
/* eof */